package lion.crawl.url;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import lion.crawl.parse.Page;

/**
 * @author Helin
 * @date 2012-8-16
 * @email hl_0074@sina.com
 * @desc 内存URL库
 * 
 * 
 */

public class RAMURLBase implements URLBase {

	private List<Page> newURLList = new ArrayList<Page>();
	private List<Page> crawled = new ArrayList<Page>();
	private List<Page> crawling = new ArrayList<Page>();

	private Lock lock = new ReentrantLock();
	Condition empty = lock.newCondition();

	@Override
	public void add(Page page) {

		try {
			lock.lock();
			if (!newURLList.contains(page) && !crawling.contains(page) && !crawled.contains(page)) {
				newURLList.add(page);
				empty.signalAll();
			}
		} finally {
			lock.unlock();
		}

	}

	@Override
	public int size() {

		try {
			lock.lock();
			return this.newURLList.size() + crawled.size() + crawling.size();
		} finally {
			lock.unlock();
		}
	}

	@Override
	public Page get() {

		Page page = null;

		lock.lock();
		try {
			while (newURLList.isEmpty()) {
				try {
					empty.await();
				} catch (InterruptedException e) {
					return null;
				}
			}
			page = newURLList.remove(0);
			crawling.add(page);
			return page;
		} finally {
			lock.unlock();
		}

	}

	@Override
	public boolean contains(Page page) {

		lock.lock();
		try {
			return newURLList.contains(page) || crawled.contains(page) || crawling.contains(page);
		} finally {
			lock.unlock();
		}
	}

	@Override
	public void crawled(Page page) {

		lock.lock();
		try {
			if (newURLList.contains(page)) {
				newURLList.remove(page);
			}
			if (crawling.contains(page)) {
				crawling.remove(page);
			}
			if (!crawled.contains(page)) {
				crawled.add(page);
			}
		} finally {
			lock.unlock();
		}
	}

	@Override
	public boolean hasNew() {

		return !newURLList.isEmpty();
	}

	@Override
	public void add(URLBase base) {

		lock.lock();
		try {
			Page page;
			while ((page = base.get()) != null) {
				if (page.isCrawled()) {
					this.crawled.add(page);
				} else {
					this.newURLList.add(page);
				}
			}
		} finally {
			lock.unlock();
		}

	}
}
